import { LayoutConfigType, Post } from '@/app/api';
import { Page, PageModel, Result } from '@/utils/request';
import Mock from 'mockjs-async';
import { MockStore } from './mock.store';
export type Service<R, P extends unknown> = (args?: P) => Promise<R>;
export type MockParam = {
  url: string;
  type?: string;
  body?: string;
}


Mock.mock('/mock/layoutConfig', 'get', (param: MockParam): Promise<Result<LayoutConfigType>> => {
  return requestHandle<LayoutConfigType, LayoutConfigType, unknown>(MockStore().getLayoutConfig, param, res => res)
});


Mock.mock('/mock/posts/create', 'put', (param: MockParam): Promise<Result<Post>> => {
  return requestHandle<Post, Post, Post>(MockStore().setPost, param, res => res)
});

Mock.mock(/\/mock\/posts\/(\d+)/, 'delete', (param: MockParam): Promise<Result<string>> => {
  return requestHandleWithUrl<string, void, number>(MockStore().deletePost,
    parseInt(param.url.match(/\/mock\/posts\/(\d+)/)[1]), res => '')
});

Mock.mock('/mock/posts/batchDelete', 'delete', (param: MockParam): Promise<Result<string>> => {
  return requestHandle<string, void, number[]>(MockStore().deleteBatchPost, param, res => '')
});


Mock.mock('/mock/posts/page', 'post', (param: MockParam): Promise<Result<PageModel<Post>>> => {
  const mockStore = MockStore();
  return requestHandle<PageModel<Post>, Post[], Page>(mockStore.postList, param, (res, p) => {
    return {
      records: res ? res.slice((p.pageNumber - 1) * p.pageSize, p.pageNumber * p.pageSize) : [],
      pageNumber: p.pageNumber,
      pageSize: p.pageSize,
      totalCount: res.length
    }
  })
});


function requestHandle<T, R, P extends unknown>(
  service: Service<R, P>,
  param: MockParam,
  tran: (res: R, p?: P) => T,
  successMsg?: string,
  errorMsg?: string): Promise<Result<T>> {
  const body = !param.body ? {} as P : JSON.parse(param.body) as P;
  return handleRequest(service, body, tran, successMsg, errorMsg);
}

function requestHandleWithUrl<T, R, P extends unknown>(
  service: Service<R, P>,
  param: P,
  tran: (res: R) => T,
  successMsg?: string,
  errorMsg?: string): Promise<Result<T>> {
  return handleRequest(service, param, tran, successMsg, errorMsg);
}

function handleRequest<T, R, P extends unknown>(
  service: Service<R, P>,
  param: P,
  tran: (res: R, p?: P) => T,
  successMsg?: string,
  errorMsg?: string): Promise<Result<T>> {
  return new Promise((resolve, reject) => {
    if (param) {
      service(param).then(res => {
        setTimeout(() => {
          resolve(
            {
              success: true,
              msg: successMsg || '成功',
              data: tran(res, param)
            }
          )
        }, 1000);
      }).catch(e => {
        reject({
          success: false,
          msg: errorMsg || '失败',
          error: {
            code: '-1',
            msg: e.message
          }
        });
      });
    } else {
      reject({
        success: false,
        msg: '参数有误',
        error: {
          code: '-1',
          msg: 'param is null'
        }
      });
    }
  });
}